目標
上一篇我們將畫面上的按鈕做了v-model的綁定
這篇會將綁定的屬性searchCondition 做處理
我們讀取Supabase會用到
後續會一一做說明
步驟
1.
如上一篇的篩選畫面
我們想要篩選出以下的結果同時行動方式為先制 且屬性是水的敵人的關卡
也就是會跟資料庫要求下面的語法
那麼下面這個語法要怎麼轉換成跟Supabase溝通的語句呢?
select * from tableName
where "element" = '水' and "skillFlag" = '先制'
由於要篩選的條件
一個在skill,另一個在enemy資料表
之後還有一些條件掛在action_event表
所以首先必須做資料表間關聯 我們才能拿這些資料去做篩選
我們要先創建一個View
(視觀表)
它實際是不存在的Table 但我們先寫好這個View
讓我們查詢時 可以直接拿來用
先回到SQL Editor 輸入以下語法
創建一個View
以skill、enemy、action_event三張表欄位做對應
create or replace view enemy_skill_view as
select enemy."rrn",enemy."element",enemy."species",
skill."skillFlag",
skill."skill1Name",
skill."skill1Value",
skill."skill1Unit",
skill."skill1Target",
skill."skill1Time",
skill."skill2Name",
skill."skill2Value",
skill."skill2Unit",
skill."skill2Target",
skill."skill2Time",
skill."skill3Name",
skill."skill3Value",
skill."skill3Unit",
skill."skill3Target",
skill."skill3Time"
from enemy
left join skill
on enemy."rrn" || enemy."posNo" = skill."rrn"
left join action_event on action_event."actionNo" || action_event."eventNo"
|| action_event."stagePrimaryNo" || action_event."stageSecNo" = enemy."rrn";
執行完畢後
來查詢這個View試試
有了這個資料表後
我們差了一個where條件
而這個API的指令文件
我們需要參考Supabase提供的官方文件
滑鼠移到左邊回到Table Editor
然後點選右上角的API Docs
滑到下面 會看到下圖這個
這段講解Filter的部分
放著我們這次需要用到的指令
由於我們需要使用的以下指令溝通
現在還差where條件
select * from enemy_skill_view
where "element" = '水' and "skillFlag" = '先制'
參考從文件提供的指令,我們需要的取用方式應該會是
supabase.from("enemy_skill_view")
.select("*")
.in("element",['水'])
.in("skillFlag",['先制'])
而為了得到以上的資料
我們需要處理v-model
綁定的searchCondition屬性
將下述searchCondition資料
[
{"checked": true, "name": "先制", "coditionType": "行動方式", "value": "1"},
{"checked": true, "name": "水", "coditionType": "敵人屬性", "value": "2"},
{"checked": false, "name": "", "coditionType": "種族", "value": "3"},
{"checked": false, "name": "", "coditionType": "標記", "value": "4"},
{"checked": false, "name": "", "coditionType": "負面狀態", "value": "5"},
{"checked": false, "name": "", "coditionType": "詛咒", "value": "5"},
{"checked": false, "name": "", "coditionType": "其他行動", "value": "5"},
{"checked": false, "name": "", "coditionType": "關卡效果", "value": "6"},
{"checked": false, "name": "", "coditionType": "憤怒條件", "value": "7"},
{"checked": false, "name": "", "coditionType": "攻擊方式", "value": "5"}
]
轉換成這樣的格式
[
{ "value": 1, "name": ["先制"] },
{ "value": 2, "name": ["水" ] }
]
所以我們在D組件這邊script程式架構追加如下
同時template也補上相對應的事件
<script setup>
async function clickToSearch(){
let arr = [];
let query = supabase.from("enemy_skill_view").select("*")
const exist1 = searchString.value.length == 0;
if(exist1){return;}
arr = searchString.value.filter(x=>x.value == 1);
if(arr.length > 0 ){query.in("skillFlag",arr[0].name) }
arr = searchString.value.filter(x=>x.value == 2);
if(arr.length > 0 ){query.in("element",arr[0].name) }
const { data, error } = await query;
if (error) {
console.error(error);
} else {
searchResult.value = data;
}
}
const searchString = computed(() => {
const checkedArr = searchCondition.value.filter(item => item.checked && item.name != "");
const groupedMap = new Map();
checkedArr.forEach(item => {
const val = Number(item.value); // 轉成數字方便排序
if(!groupedMap.has(val)) groupedMap.set(val, []);
groupedMap.get(val).push(item.name);
});
return Array.from(groupedMap.entries())
.map(([value, name]) => ({ value, name }))
})
</script>
●
這邊有一點要注意的是
因為Supabase取資料為非同步動作 記得在函式紅框處加async
●
查詢指令是可以拆開寫的
所以像藍框的地方 就可以依據判斷加上過濾條件
那麼到了這一步,取得的資料就可以提供給R組件
R組件和F組件呈現方式相似
因為結構類似可以照搬
篩選結果後會呈現如下圖的畫面
按下關卡Stage的文字後 應該左邊會呈現敵人資訊
然而你會發現,你會訝異
現在是開不起來的 因為此時其實有顯示的BUG
A組件的程式結構要稍微調整如下
假設D組件傳回A組件的資料是msg3
那麼showStageList這邊要加上兩行判斷
否則會發生切換顯示的BUG
<script setup>
const showStageList = computed(() => {
if (props.msg2 && props.msg2 !== "") {return true;}
if (props.msg3 && props.msg3 !== "") {return true;}
return Array.isArray(props.msg) && props.msg.length === 1 && Object.keys(props.msg[0]).length === 0
? false
: true;
})
</script>
修好後,技能正常篩選畫面如下圖 符合我們預期結果
回顧這兩篇,我們從資料重新規劃到匯入
再到v-model
管理資料一直到資料處理
之後整理我們需要交給Supabase的語法
最後將結果送給R組件顯示
備註
Supabase提供的文件裡頭的語法
包含or()
、in()
、eq()
..等是有另外在做參數化的處理的
(如筆者有錯誤理解 再煩請留言告知)
所以對於SQL Injection的問題
如果擔心的話 還是可以對使用者輸入或者最後送去DB資料提前過濾
也讓自己安心
但資安問題廣泛 不在這篇討論